package com.springStudy.boot.redis.seconedDemo.jedis;

import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

@Component
public class TestDemo1 {
//    @Resource(name = "stringRedisTemplate")
    private static RedisTemplate<String, String> stringRedisTemplate;

    /**
     * 由于多线程导致资源不被释放，发生死锁
     */
    public static void test01() {
        stringRedisTemplate.setEnableTransactionSupport(true);//单例这里切换为使用事务，这里只做测试使用。
        try {
            String preOrderSeq = "1111";
            for (int i = 0; i < 10; i++) {
                String getOrderSeq = stringRedisTemplate.boundValueOps("test" + preOrderSeq+i).get();
//               stringRedisTemplate.boundValueOps("test" + preOrderSeq+i).set("test"+i);

                System.out.println("------" + i);
            }


            AtomicInteger inc = new AtomicInteger(0);
            AtomicInteger callRedisCount = new AtomicInteger(0);

            final CountDownLatch latch = new CountDownLatch(100);

            for (int i = 0; i < 100; i++) {
                final int counter = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        int a = inc.incrementAndGet();
                        System.out.println("启动线程：-" + Thread.currentThread().getId() + "- : " + a);
                        try {
                            latch.await();


                            String getOrderSeq = stringRedisTemplate.boundValueOps("" + preOrderSeq).get();
//                            stringRedisTemplate.boundValueOps("test" + preOrderSeq).set("test");

                            int count = callRedisCount.incrementAndGet();
                            System.out.println("执行了多少次redis操作：" + Thread.currentThread().getId() + " : " + count);
                            System.out.println("结束线程：-" + Thread.currentThread().getId() + "- : " + a);
//                        RedisUtil.getTemplate().boundValueOps(Constants.ORDER_LOCKE_KEY + preOrderSeq).set(preOrderSeq, 10, TimeUnit.SECONDS);
//                        System.out.println(counter + ":" + getInfo(jedisPool));
                        } catch (InterruptedException e) {
                            System.out.println("结束线程：-" + Thread.currentThread().getId() + "- : " + a);
                            e.printStackTrace();
                        }
                    }
                }).start();
                latch.countDown();
            }

        } catch (Throwable t) {
            System.out.println(t);
        }
        try {
            Thread.sleep(1000 * 600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    /**
     * 使用事务的正确姿势，
     * 通过 org.springframework.data.redis.core.RedisConnectionUtils#unbindConnection 方法检查该事务是否完成，完成就关闭链接
     */
    public static void test02() {
        stringRedisTemplate.setEnableTransactionSupport(true);//单例这里切换为使用事务，这里只做测试使用。
        try {
            String preOrderSeq = "1111";
            for (int i = 0; i < 10; i++) {
                final int j = i;
                List<Object> txResults = stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
                    public List<Object> execute(RedisOperations operations) throws DataAccessException {
                        operations.multi();
                        operations.opsForSet().add("key"+j, "value_"+j);
                        // This will contain the results of all ops in the transaction
                        return operations.exec();
                    }
                });

//                System.out.println("result:" + result);
                System.out.println("------" + i);
            }


            AtomicInteger inc = new AtomicInteger(0);
            AtomicInteger callRedisCount = new AtomicInteger(0);

            final CountDownLatch latch = new CountDownLatch(100);

            for (int i = 0; i < 100; i++) {
                final int counter = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        int a = inc.incrementAndGet();
                        System.out.println("启动线程：-" + Thread.currentThread().getId() + "- : " + a);
                        try {
                            latch.await();

                            List<Object> txResults = stringRedisTemplate.execute(new SessionCallback<List<Object>>() {
                                public List<Object> execute(RedisOperations operations) throws DataAccessException {
                                    operations.multi();
                                    operations.opsForSet().add("key"+preOrderSeq, "value_"+preOrderSeq);
                                    // This will contain the results of all ops in the transaction
                                    return operations.exec();
                                }
                            });

                            int count = callRedisCount.incrementAndGet();
                            System.out.println("执行了多少次redis操作：" + Thread.currentThread().getId() + " : " + count);
                            System.out.println("结束线程：-" + Thread.currentThread().getId() + "- : " + a);
//                        RedisUtil.getTemplate().boundValueOps(Constants.ORDER_LOCKE_KEY + preOrderSeq).set(preOrderSeq, 10, TimeUnit.SECONDS);
//                        System.out.println(counter + ":" + getInfo(jedisPool));
                        } catch (InterruptedException e) {
                            System.out.println("结束线程：-" + Thread.currentThread().getId() + "- : " + a);
                            e.printStackTrace();
                        }
                    }
                }).start();
                latch.countDown();
            }

        } catch (Throwable t) {
            System.out.println(t);
        }
        try {
            Thread.sleep(1000 * 600);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Resource(name = "stringRedisTemplate")
    public void setStringRedisTemplate(RedisTemplate<String, String> stringRedisTemplate) {
        TestDemo1.stringRedisTemplate = stringRedisTemplate;
    }
}
